package com.redis.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author huyunqiang
 * @Date 2019/10/20 12:38
 */
public class RedisType5Test {


        @Autowired
        @Qualifier("redisTemplate1")
        private RedisTemplate<Serializable, Object> redisTemplate1;
        /**
         * 登录次数验证
         * @param key
         * @param retriesLifecycleTime 多长时间内重试有效(秒)
         */
        public Long setloginRetriesLockNum(String key, int retriesLifecycleTime) {
            String retriesLockscript = "local errorNum = redis.call('get',KEYS[1]) "
                    + "if errorNum == false "
                    + "then errorNum = redis.call('incr',KEYS[1]) redis.call('expire',KEYS[1],tonumber(ARGV[1])) return errorNum "
                    + "else return redis.call('incr',KEYS[1]) end";
            Long retriesLockNum = executeScript(retriesLockscript, 1, key, String.valueOf(retriesLifecycleTime));
            return retriesLockNum;
        }

        /**
         * 登录次数多，锁定
         * @param key
         * @param retriesLifecycleTime 多长时间内重试有效(秒)
         * @param retriesNum 重试次数
         * @param lockTime 锁定时间(秒)
         * @return 锁定true，否则false
         */
        public boolean loginLock(String key,int lockTime) {
            String lockKey = key+"_lock";
            String lockScript = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 "
                    + "then redis.call('expire',KEYS[1],tonumber(ARGV[2])) return 1 "
                    + "else return 2 end";
//            String nowTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:dd:ss");
            SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String nowTime = sdf.format(new Date());
            Long isLocked = executeScript(lockScript, 1, lockKey, nowTime, String.valueOf(lockTime));
            return isLocked != null && isLocked==1 ? true : false;
        }

        /**
         * 删除重置lock
         * @param key
         * @return
         */
        public boolean delLoginRetriesLock(String key) {
            if(redisTemplate1.hasKey(key)) {
                redisTemplate1.delete(key);
                return true;
            } else {
                return false;
            }
        }

        /**
         * 得到失败次数
         * @param key
         * @return
         */
        public Long getLoginRetriesLockNum(String key) {
            String retriesLockscript = "return redis.call('get',KEYS[1]) ";
            String errorNum = executeScript(retriesLockscript, 1, key);
            return StringUtils.isEmpty(errorNum) ? 0L : Long.parseLong(errorNum);
        }

        /**
         * 是否锁定
         * @param key
         * @return 锁定 true，否则false
         */
        public boolean isLoginLock(String key) {
            String lockKey = key+"_lock";
            String lockScript = "return redis.call('get',KEYS[1]) ";
            String lockVlaue = executeScript(lockScript, 1, lockKey);
            return StringUtils.isEmpty(lockVlaue) ? false : true;
        }

        private <T> T executeScript(final String script, final int keyCount, final String... values) {
            T value = redisTemplate1.execute(new RedisCallback<T>(){
                @SuppressWarnings("unchecked")
                @Override
                public T doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    Jedis jedis = (Jedis) connection.getNativeConnection();
                    return (T) jedis.eval(script, keyCount, values);
                }
            });
            return value;
        }

}
